package m3f.factorization;

import org.jblas.DoubleMatrix;
import org.jblas.MatrixFunctions;

import m3f.computing.ConcurrentTemplate;
import m3f.data.MultimodalDataProvider;
import m3f.matrix.Minibatch;

public class ConcurrentErrorNSE extends ConcurrentTemplate{
	
	private MultimodalDataProvider data;
	private DoubleMatrix S;
	private double error;
	
	public ConcurrentErrorNSE(MultimodalDataProvider trainingData, DoubleMatrix S, double beta){
		super(trainingData.matrixRows()/trainingData.getMinibatchSize()+1);
		this.data = trainingData;
		this.S = S;
		error = 0;
	}

	public double getError(){
		return error;
	}
	
	@Override
	public void singleOperation(int reg) {
		Minibatch V, T;
		//long s = System.currentTimeMillis();
		synchronized (data) {
			V = data.nextVisual();
			T = data.nextTextual();
		}
		DoubleMatrix ratio;
		DoubleMatrix Vc = S.mmul(T.matrix());
		ratio = MatrixFunctions.log(V.matrix().div(Vc.add(0.000001)).add(0.000001));
		double e = Math.pow(V.matrix().mul(ratio).sub(V.matrix()).add(Vc).norm2() / 1000000,2.0);
		//double e = V.matrix().sub(Vc).norm2();
		synchronized (this){
			error += e;
		}
		//System.out.println("Error for minibatch: " + (System.currentTimeMillis()-s) + " ms");
	}
}
